﻿#ifndef DEBUGLOG_H
#define DEBUGLOG_H

#include <QDir>

#include <QTime>
#include <QDebug>

#include <QSqlQuery>
#include <QSqlError>
#include <QSqlDatabase>
#include "QmlSignal.h"

#define DEBUG_SOFTWARE_NAME "96-RT-PCR"

// 打印级别
#define DEBUG_MODE 2        // 0 不打印
                            // 1 用户环境
                            // 2 测试环境

// ============================== 调用接口Start ======================================

// 日志打印 (a可传入任意类型参数，输出格式和qDebug()打印的格式相同)
#define __LOG_DEBUG(a)  DebugLog::I().debug(DEBUG_CONTEXT, a)
#define __LOG_WARN(a)   DebugLog::I().warning(DEBUG_CONTEXT, a)
#define __LOG_ERROR(a)  DebugLog::I().error(DEBUG_CONTEXT, a)
#define __LOG_INFO(a)   DebugLog::I().info(DEBUG_CONTEXT, a)

// 函数开始和结束时调用 (带参数)
#define __LOG_FSTART(a) DebugLog::I().funcStart(DEBUG_CONTEXT, a)
#define __LOG_FEND(a)   DebugLog::I().funcEnd(DEBUG_CONTEXT, a)
// 函数开始和结束时调用 (不带参数)
#define __LOG_FSTART__  DebugLog::I().funcStart(DEBUG_CONTEXT)
#define __LOG_FEND__    DebugLog::I().funcEnd(DEBUG_CONTEXT)

// 循环开始和结束时调用
#define __LOG_CSTART(a) DebugLog::I().cycleStart(DEBUG_CONTEXT, a)
#define __LOG_CEND(a)   DebugLog::I().cycleEnd(DEBUG_CONTEXT, a)


// ============================== 调用接口End =======================================


// 打印当前函数信息
//#define DEBUG_CONTEXT   QString(__FILE__).split("/").back() + " Line" + QString("%1").arg(__LINE__, 3, 10, QLatin1Char('0')) + " " + QString(__func__) +  "()"
#define DEBUG_CONTEXT     QString(__FILE__).split("/").back().remove(".cpp") + "  " + QString(__func__) + "()"

#ifdef Q_OS_ANDROID
#define DEBUG_ONSCREEN true
#else
#define DEBUG_ONSCREEN false
#endif


class DebugLog
{

private:
    DebugLog();

public:
    static DebugLog& I();

    void write(QString text, int type=0);      // type=0一般日志 1sql日志 2通信日志


    // ========================= 函数开始和结束 ================================
    void funcStart(QString context){
        if(DEBUG_MODE == 0) return;
        write("[FSTA]  " + context);
    }
    void funcEnd(QString context){
        if(DEBUG_MODE == 0) return;
        write("[FEND]  " + context);
    }

    template<typename T>
    void funcStart(QString context, T text){
        if(DEBUG_MODE == 0) return;
        write("[FSTA]  " + context + "  " + qobj2qstr(text));
    }
    template<typename T>
    void funcEnd(QString context, T text){
        if(DEBUG_MODE == 0) return;
        write("[FEND]  " + context + "  " + qobj2qstr(text));
    }

    // =========================== 循环开始和结束 ===============================
    template<typename T>
    void cycleStart(QString context, T text){
        if(DEBUG_MODE == 0) return;
        write("[CSTA]  " + context + "  " + qobj2qstr(text));
    }
    template<typename T>
    void cycleEnd(QString context, T text){
        if(DEBUG_MODE == 0) return;
        write("[CEND]  " + context + "  " + qobj2qstr(text));
    }


    // ========================== 其它通用类型 ===============================
    template<typename T>
    void debug(QString context, T text){
        if(DEBUG_MODE < 2) return;
        write("[DEBU]  " + context + "  " + qobj2qstr(text));
    }
    template<typename T>
    void info(QString context, T text){
        if(DEBUG_MODE == 0) return;
        write("[INFO]  " + context + "  " + qobj2qstr(text));
    }

    template<typename T>
    void warning(QString context, T text){
        if(DEBUG_MODE == 0) return;
        write("[WARN]  " + context + "  " + qobj2qstr(text));
    }

    template<typename T>
    void error(QString context, T text){
        if(DEBUG_MODE == 0) return;
        write("[ERRO]  " + context + "  " + qobj2qstr(text));
    }

    // ============================= 其它日志类型 ==================================
    void sql(QString sql, QString res, QString info){      // 数据库日志
        if(DEBUG_MODE < 2) return;
        write(res + "  " + sql + "  [RES]" + info, 1);
    }
    void communication(QString text, int type){      // 0 发送 1 接收
        write((type==0?"[SEND]":"[RECV]  ") + text, 2);
    }



    // 将不知道什么类型的东西转成字符串类型
    template<typename T>
    QString qobj2qstr(T obj){
        QString str;
        QDebug debug(&str);
        debug << obj;
        return str;
    }

    QString    _outRootDir;
    int        _deleteTime = 10;     // 删除天数间隔

};

// QSqlQurery重载，用于打印执行的SQL语句
class QSqlQueryDebug : public QSqlQuery{

    // 数据库返回结果行数
    int sqlSize(QSqlQuery* query){
        int initialPos = query->at();
        int pos = 0;
        if (query->last())  pos = query->at() + 1;
        query->seek(initialPos);
        return pos;
    }
public:

    QSqlQueryDebug(QSqlDatabase db) : QSqlQuery(db){
    }
    QSqlQueryDebug(const QString& query = QString(), QSqlDatabase db = QSqlDatabase()) : QSqlQuery(query, db){
    }
    QSqlQueryDebug(QSqlResult *r) : QSqlQuery(r){
    }

    bool exec(){
        return QSqlQuery::exec();
    }
    bool exec(const QString& query){
        bool res = QSqlQuery::exec(query);
        if(res){
            DebugLog::I().sql(query, "[SUCC]", QString::number(sqlSize(this)));
        }else{
            DebugLog::I().sql(query, "[FAIL] ", this->lastError().text());
        }
        return res;
    }

};

#define QSqlQuery QSqlQueryDebug

#endif // DEBUGLOG_H
